package cn.shop.cloud.service.impl;

import cn.shop.cloud.common.BusinessException;
import cn.shop.cloud.common.Result;
import cn.shop.cloud.domain.Good;
import cn.shop.cloud.domain.SeckillGood;
import cn.shop.cloud.feign.GoodFeignApi;
import cn.shop.cloud.mapper.SeckillGoodMapper;
import cn.shop.cloud.redis.MyRedisTemplate;
import cn.shop.cloud.service.ISeckillGoodService;
import cn.shop.cloud.web.mq.MQConstants;
import cn.shop.cloud.web.msg.SeckillCodeMsg;
import cn.shop.cloud.web.redis.SeckillKeyPrefix;
import cn.shop.cloud.web.vo.SeckillGoodVo;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @program: shop-parent
 * @ClassName SeckillGoodServiceImpl
 * @description:
 * @author: Mokio
 * @create: 2024−12-24 21:11
 * @Version 2024 2.2 ; jdk1.8.0_181
 **/
@Service
public class SeckillGoodServiceImpl  implements ISeckillGoodService {

    @Autowired
    private SeckillGoodMapper seckillGoodMapper;

    @Qualifier("cn.shop.cloud.feign.GoodFeignApi")
    @Autowired
    private GoodFeignApi goodFeignApi;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private MyRedisTemplate redisTemplate;


    @Override
    public List<SeckillGoodVo> query() {
        /*
          做三件事 :
            1. 单表查询 t_seckill_goods  所有参与秒杀商品的数据 得到 seckillGoodList
            2.获取到所有的参与秒杀商品的 good_id [1,2,3,4,5....]
            3.调用 good-server 远程方法  ，传递参数 [1,2,3,4,5....] 根据参数 在商品微服务中查询 t_goods 数据 GoodList


         */

        // 1. 单表查询 t_seckill_goods  所有参与秒杀商品的数据 得到 SeckillGoodList
        List<SeckillGood> seckillGoodList = seckillGoodMapper.query();

        //  2  和  3 放一个里面   ctrl + Alt +M
        List<SeckillGoodVo> seckillGoodVoList= getSeckillGoodVos(seckillGoodList);


        return seckillGoodVoList;
    }

    @Override
    public SeckillGoodVo find(Long seckillId) {
        if(seckillId==null){
            return  null;
        }

        SeckillGood sg= seckillGoodMapper.get(seckillId);

        if(sg==null){
            return  null;
        }

        List<SeckillGood> seckillGoodList = new ArrayList<>();
        seckillGoodList.add(sg);

        List<SeckillGoodVo> seckillGoodVoList = getSeckillGoodVos(seckillGoodList);

        return seckillGoodVoList.get(0);
    }

    @Override
    public void decrStock(Long seckillId) {
        seckillGoodMapper.decrStock(seckillId);
    }

    /**
     * 库存回补
     * @param seckillId
     */
    @Override
    public void syncRedisStcokCount(Long seckillId) {
        //根据场次id  查询一下库存数量
        int stockCount=  seckillGoodMapper.getStockCount(seckillId);
        if(stockCount>0){
            //说明有库存
            rabbitTemplate.convertAndSend(MQConstants.SECKILL_OVER_SIGN_PUBSUB_EX,"",seckillId);
            stockCount++;
            //设置redis中库存数量
            redisTemplate.set(SeckillKeyPrefix.SECKILL_STOCK_COUNT,seckillId+"",stockCount);

        }

    }

    @Override
    public void incrStock(Long seckillId) {
        seckillGoodMapper.incrStock(seckillId);
    }

    private  List<SeckillGoodVo> getSeckillGoodVos(List<SeckillGood> seckillGoodList) {

        //    2.获取到所有的参与秒杀商品的 good_id [1,2,3,4,5....]  开始了
        Set<Long> idSet = new HashSet<>();//集合存id数据
        for(SeckillGood sg:seckillGoodList){
            idSet.add(sg.getGoodId());//拿到商品编号添加到集合中

        }
        //将set 转为 list
        List<Long> ids = new ArrayList<>(idSet);// [1,2,3]
        //  2 结束了

        //第三步  调用 good-server 远程方法  ，传递参数 [1,2,3,4,5....] 根据参数 在商品微服务中查询 t_goods 数据 GoodList
        Result<List<Good>> result = goodFeignApi.queryByIds(ids);  //远程调用

        if(result==null ||result.hasError()){
            //说明 远程调用失败了
            throw new BusinessException(SeckillCodeMsg.PRODUCT_SERVER_ERROR);
        }

        //远程调用没有错误
        List<Good> goodList = result.getData();//获取数据

        //通过goodId 找 Good
        Map<Long,Good> goodMap = new HashMap<>();
        for(Good good:goodList){
            goodMap.put(good.getId(),good);
        }
        //把数据内存中进行聚合
        List<SeckillGoodVo> seckillGoodVoList = new ArrayList<>();

        for (SeckillGood sg:seckillGoodList){
            //获取商品信息
            Good good = goodMap.get(sg.getGoodId());
            //将 SeckillGood   和 Good 封装成vo对象
            SeckillGoodVo vo = new SeckillGoodVo();
            vo.setGoodDetail(good.getGoodDetail());//商品详细
            vo.setGoodName(good.getGoodName());
            vo.setGoodImg(good.getGoodImg());
            vo.setGoodPrice(good.getGoodPrice());//商品原价
            vo.setGoodTitle(good.getGoodTitle());
            vo.setEndDate(sg.getEndDate());//秒杀结束时间
            //商品id
            vo.setGoodId(good.getId());
            vo.setSeckillPrice(sg.getSeckillPrice());//秒杀价
            vo.setStartDate(sg.getStartDate());//秒杀开始时间
            vo.setStockCount(sg.getStockCount());//参与秒杀的数量
            vo.setId(sg.getId());//场次id  ???

            //添加兑现到集合中
            seckillGoodVoList.add(vo);

        }

        return seckillGoodVoList;
    }
}